package com.riteny.mybatis.scanner;

import org.apache.commons.lang.ArrayUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.reflections.Reflections;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Repository;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.Set;

/**
 * @author Riteny
 * 2019/12/13  10:03
 */
public class RepositoryConfigScanner {

    @Value("${mybatis.scanner.base.package}")
    private String basePackage;

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        sessionFactoryBean.setMapperLocations(getResources());
        return sessionFactoryBean.getObject();
    }

    @Bean
    public MapperScannerConfigurer getMapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setAnnotationClass(Repository.class);
        mapperScannerConfigurer.setBasePackage(basePackage);
        return mapperScannerConfigurer;
    }

    public Resource[] getResources() throws IOException {
        Resource monthlyResources[] = new Resource[0];
        Reflections reflections = new Reflections(basePackage);
        Set<Class<? extends RepositoryInfoProvider>> monitorClasses = reflections.getSubTypesOf(RepositoryInfoProvider.class);
        for (Class<? extends RepositoryInfoProvider> monitor : monitorClasses) {
            RepositoryInfoAnnotation annotation = monitor.getAnnotation(RepositoryInfoAnnotation.class);
            for (String resource : annotation.resources()) {
                monthlyResources = (Resource[]) ArrayUtils.addAll(monthlyResources, new PathMatchingResourcePatternResolver().getResources(resource));
            }
        }
        return monthlyResources;
    }
}
